package com.xfatm.util.merge;

import com.xfatm.util.typecase.TypeCaseUtils;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * 对象属性合并，依赖于TypeCaseUtils
 */
public class MergeUtils {
    /**
     * 对象合并
     * @param setObj 需要合并的对象
     * @param getObj 被合并的对象
     * @param option 合并列配置
     */
    public static void mergeObject(Object setObj,Object getObj,String option) throws Exception{
        for(String cfg:option.split(",")){
            Object getObject=getObj;
            for(String name:cfg.split("=")[1].split("\\.")){
                if(getObject instanceof Map){
                    getObject=getObject.getClass().getDeclaredMethod("get",Object.class).invoke(getObject,name);
                }else{
                    getObject=getObject.getClass().getDeclaredMethod(getMethodName(name,"get")).invoke(getObject);
                }
            }
            Object setObject=setObj;
            Method setMethod=null;
            String[] setField=cfg.split("=")[0].split("\\.");
            String setName=null;
            for(int i=0;i<setField.length;i++){
                setName=setField[i];
                if(i==setField.length-1){
                    if(setObject instanceof Map){
                        setMethod=setObject.getClass().getDeclaredMethod("put",Object.class,Object.class);
                    }else{
                        setMethod=getMethod(setObject,getMethodName(setName,"set"));
                    }
                    break;
                }
                if(setObject instanceof Map){
                    setObject=setObject.getClass().getDeclaredMethod("get",Object.class).invoke(setObject,setName);
                }else{
                    setObject=setObject.getClass().getDeclaredMethod(getMethodName(setName,"get")).invoke(setObject);
                }
            }
            Class<?>[] types=setMethod.getParameterTypes();
            if(types==null||types.length>2){
                System.out.println("方法参数错误"+types);
                return;
            }
            if(setObject instanceof Map){
                setMethod.invoke(setObject,setName,get2SetObject(getObject,types[0]));
            }else{
                setMethod.invoke(setObject,get2SetObject(getObject,types[0]));
            }

        }
    }

    private static Object get2SetObject(Object getObject,Class<?> setType){
        if(getObject==null){
            return null;
        }
        for(Class<?> c=getObject.getClass();;c=c.getSuperclass()){
            if(c.getName().equals(setType.getName())){
                return getObject;
            }
            if(c==Object.class){
                break;
            }
        }
        return typeCase(getObject,setType);
    }

    private static Object typeCase(Object obj,Class<?> type){
        return TypeCaseUtils.typeCase(obj,type);
    }

    private static Method getMethod(Object obj,String name){
        for(Method m:obj.getClass().getMethods()){
            if(name.equals(m.getName())){
                return m;
            }
        }
        return null;
    }

    private static String getMethodName(String name,String head){
        return head+name.substring(0,1).toUpperCase()+name.substring(1);
    }
}
